home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SoundMaker 2003 (Professional Edition)
/
SoundMaker 2003 - Professional Edition.iso
/
music workstation
/
ptwdemo.exe
/
{app}
/
ptwdll.txt
< prev
next >
Wrap
Text File
|
2002-04-25
|
43KB
|
903 lines
INTERFACING A .DLL or .EXE WITH POWERTRACKS
This document applies to both .DLL and .EXE support, even though
there are minor differences in behavior of .EXEs vs. DLLs. These
differences, along with information about .EXE support, will be
discussed later in this document.
NOTE: Starting with PowerTracks Version 8.0, only 32-bit .DLLs and
.EXEs can link to PowerTracks. Any 16-bit .DLL or .EXE programs
need to be recompiled as 32-bit. Also, 32-bit .DLLs and .EXEs will
not work with earlier version of PowerTracks. We suggest you focus
only on creating 32-bit .EXEs since future versions of PowerTracks
will be 32-bit only.
NOTE: Since a 32-bit .EXE is NOT allowed to pass a pointer directly
to another 32-bit .EXE, it is now required that you use a Memory
Mapped File each time the .EXE passes a structure or string to
PowerTracks. While this is inconvenient, it is not that
complicated, and the EXEDEMO.DPR contains sample source code that
makes it clear how to deal with Memory Mapped Files. The
EXEDEMO.ZIP file containing the EXEDEMO project, contains a
MEMMAP.PAS which can be used to easily create Memory Mapped Files
as needed.
For EXE programs: the rule is that you can NEVER pass anything to
PowerTracks as a pointer, so you have to first create a Memory
Mapped File for the structure you wish to pass. These Memory
Mapped Files are NOT actual files on disk, but, when created, the
Memory Mapped Files are given names that are used to identify them,
and you must name them correctly so PowerTracks will recognize
them.
If You're using an .EXE, you would create memory mapped files
within your .EXE using the exact file names discussed later in this
document. For any message that formerly required a pointer,
you would pass zero (Nil), since PTW will be use an API call to open for the
memory mapped file name that is specific to the message you're
sending to PTW.
NOTE REGARDING DLLS: If you are interfacing a .DLL with
PowerTracks, you do not need to use Memory Mapped Files. You can
pass structures directly as pointers in the LParam parameter of
a SendMessage, and PTW will use those pointers instead of attempting
to open a memory mapped file. You could use Memory Mapped Files if
you wanted to with a .DLL but, it would probably be easier to just
pass pointers directly to the .EXE.
For example, if you wish to pass the TExeInfo structure, you create a
Memory Mapped File called 'PTWExeInfo', and this file is equal in
size to the TExeInfoStructure. Each structure that gets passed to PTW,
will have a corresponding name that must be used when creating the Memory Mapped File
for the structure.
Here are a list of the structures and the corresponding names:
(unless otherwise noted, the file sizes must be set to the sizes of
the structures)
TExeInfo --> 'PTWExeInfo' is the name used for the Memory Mapped File
TTrackInfo --> 'PTWTrackInfo' is the name used for the Memory Mapped File
TIndexedMIDIData ---> 'PTWIndexedMIDIData' is the name used for the Memory Mapped File
PChar ----> 'PTWString' is the name used for the Memory Mapped File in order
to pass a PChar string (such as a file name, etc.) to PowerTracks.
This file should be always be 257 bytes in size, regardless of how
small a string you intend to pass to PTW.
For example, when retrieving information about a track in PowerTracks,
you must first create this Memory Mapped File:
---------------------------------------------------------------
Uses MemMap;
Var TrackMemMap:TMemMap; TrackInfo:PTrackInfo;
TrackMemMap := TMemMap.Create('PTWTrackInfo',SizeOf(TTrackInfo));
If TrackMemMap = Nil then exit;
TrackInfo := PTrackInfo(TrackMemMap.GetMemPtr);
SendMessage(WinHandle,wm_MD_SetTrackNumber,SpinEdit1.Value,0);
SendMessage(WinHandle,wm_MD_GetTrackInfo,0,0);
--------------------------------------------------------------
In the Above code, the Memory Mapped File called 'PTWTrackInfo' is created
with a size equal to the size of the TTrackInfoStructure. The file must be named
exactly as 'PTWTrackInfo' because PowerTracks will look for that file when
the wm_MD_GetTrackInfo or wm_MD_SetTrackInfo commands are received by PowerTracks.
If you are using Memory Mapped Files, you must ALWAYS set the lparam field to zero.
NOTE: The structures have changed in that they no longer contain
any embedded pointers. For example, a structure that contained a
PChar will now contain an array [0..128] of char. A structure
containing a pointer to an array will now include the actual array.
You can use the language of your choice (C++, Pascal, Delphi etc.)
Once created, the .DLL (or .EXE) can be used by PowerTracks,
and will appear to the user as a button on the Mixer Screen. Inside
the .DLL (or .EXE), you will have easy access to the MIDI data that
PowerTracks is receiving and sending out, and will also easily be
able to send out your own MIDI data to your synthesizer.
Examples of possible .DLLs (or .EXEs) that could be created are:
- 'front panel' type functionality for a specific synthesizer.
- editor/ librarian for a synthesizer.
- utility program - MIDI monitor
- displaying MIDI data in a custom format or in a graphical way.
- using MIDI data to trigger graphics etc.
***************************************************************
NOTE: This documentation covers the Programming of .DLLs using
PowerTracks. This is nothing to do with the international language
support .DLLs you can make for other language support like French,
Spanish etc. If you are interested in making an international version
of PowerTracks (or another PG Music program), you'll need different
documentation, please contact us for this.
****************************************************************
When you create the .DLL (or .EXE), you name it starting with a $
sign, and put it in the PowerTracks directory c:\pt. When the user
selects a .DLL (or .EXE), the .DLL and .EXE files with a $ sign
will appear in the list, and he can choose your .DLL or .EXE.
In the case of a .DLL, once your DLL is chosen, the DLL is run and
you are passed a structure that contains information like: - the
Handle of the MIDI Output device that PowerTracks is set to use.
(Interfacing with an .EXE involves sending the wm_MD_EXESignIn to
obtain the same structure that is passed to .DLLs, and will be
discussed later in this document.)
You can use the output handle immediately inside your .DLL by
calling the MIDIOutShortMsg routine with the handle, and the
MIDIData that you want to send out. If your application is only
sending MIDI out (and not processing input), then this Handle is
virtually the only piece of information that you need.
************IMPORTANT INFO REGARDING EXE PLUGINS***************
It appears that WinXP doesn't support the sharing of MIDI output
ports between two different applications, so we created a
WM_MD_SendShortMsg that lets your .EXE plugin send a MIDI short message
via PowerTracks without your plugin needing to open it's own MIDI
Output port. DLL MIDI Plugins can still call MidiOutSHortMsg
directly.
****************************************************************
- a circular buffer prepared by PowerTracks with all the
incoming MIDI data that is coming from MIDI thru (that the
user is playing) as well as the outgoing data that PowerTracks
is sending. This buffer includes regular MIDI data, as well
as Sys-EX events. If your application is processing the data
in this buffer (for a MIDI monitor for example), then it will
be regularly reading this buffer.
You can use any language that is capable of compiling to a .DLL or
.EXE. This includes C,C++, Pascal and Delphi.
The advantages of creating a .DLL (or .EXE) to use in PowerTracks
are:
- The .DLL or .EXE is easily accessible to the user as it appears
as a button on the Mixer Window, and via a menu item starting with
PTW 3.0b.
- the .DLL or .EXE uses the same output handle, and input buffer
as PowerTracks, overcoming the limit of '1 application per driver'
that many applications have,
- simplifies Windows MIDI programming. You don't need to worry
about finding the output handle to use, or worry about collecting
the incoming data in a buffer. This is done for you.
- re-usability. Other PG Music programs (Band-in-a-Box, The Pianist
may soon support these .DLLs and .EXEs, so that when you create a
.DLL or .EXE for PowerTracks, it will also work for these other
programs, (NOTE: this is assuming that the .DLL/.EXE doesn't do
things that are unsupported by the other programs. For example,
since the Pianist is not a sequencer it may not support all the new
editing messages that PowerTracks does.)
Questions regarding the documentation or DLL/EXE programming
should be addressed to support@pgmusic.com
*************************************************
The following documentation is in Pascal. If using C, you'd need
to convert this Procedure to Pascal.
We include a complete sample application called GS Reset, which
compiles to a .DLL. This simple .DLL has a button that resets
a GS synthesizer, and will give you a simple introduction to
the .DLL programming. This GSRESET code is found in the file
GSRESET.ZIP. The GS RESET code is in 'Delphi' , which is the
newest implementation of Pascal for Windows from Borland .
We also include a demo exe in EXEDEMO.ZIP, which is a demo .EXE
written in Delphi with complete source code.
A .DLL must have the following procedure, which is called by
PowerTracks:
Procedure
LaunchTheDialog(HWindow:Hwnd;TheCurrentPart:Integer;PortHandle:THandle;
TheMIDIInfo:PMIDIInfo;ProgNum,Language:Byte);
Export;
You should make sure that the LaunchTheDialog procedure exits
gracefully if is called twice before the first call to the dialog
finished executing. If you don't do this then there could be
problems if we added .DLL support to other programs and two
programs attempted to use the same .DLL at the same exact time.
Also, the .DLL should still remain in memory even if the user
closes the dialog, because PowerTracks will assume the .DLL is
still active and could call the LaunchTheDialog procedure again
if the user presses the <Run DLL> button.
Note: A dialog can show a normal window instead of a dialog when
the LauchTheDialog procedure is called. This would let the user
switch back and forth between the window and PowerTracks while the
.DLL is loaded. However, your .DLL should be written in such a way
that it exits the LaunchTheDialog procedure if called while the
window is already currently displayed, rather than displaying
duplicate windows!
The HWindow is a handle to the mixer window of PowerTracks. This
may be needed if your programming language requires a parent window
to launch a dialog from within a .DLL, or when the .DLL sends a
message to the mixer window such as WM_BufferNotNeeded (explained
below).
TheCurrentPart is the current part number or channel number of a 16
part synth. You can ignore this if the .DLL you're writing isn't
for a specific synth.
The PortHandle is a handle to a MIDIOutput port in PowerTracks. It
is the output port of the current track. You can use this handle
when calling multimedia API functions such as midiOutShortMsg.
TheMIDIInfo is pointer with a type of PMIDIInfo, which is a pointer
to a TMIDIInfo data structure. The Definition of PMIDIInfo is as
follows:
PMIDIInfo = ^TMIDIInfo;
TMIDIInfo = Record
TheMIDIEventArray:PMIDIEventArray {Pointer to a circular buffer array};
MIDIEventHead,MIDIEventTail:Word; {Head and Tail of buffer}
SysExArray:PSysExArray; {Pointer to the array of Sysex data}
End;
The MIDIEventArray, and SysExArray are two items that are used if a
.DLL needs to receive output message from PowerTracks. These items
can be ignored by a .DLL or .EXE that doesn't need them. If a program
doesn't need to use these items it should send a special message to
the handle of the window that was passed in the HWindow parameter
of LaunchTheDialog. This message is as follows:
Const wm_BufferNotNeeded = wm_User + 33;
e.g SendMessage(HWindow,wm_user+33,0,0);
This tells PowerTracks a .DLL or .EXE won't be using the buffers
so it doesn't have to waste time filling them.
Keep in mind that using these buffers requires that you install a
timer to read them often, such as a WM_TIMER, which may not be
adequate, or preferably a multimedia timer, which is much more
accurate. Reading and processing these buffers in a .DLL or .EXE
could possibly take significant time away from PowerTracks to be
able to do things like redraw screens quickly, etc. so this feature
may be only desirable on fast 486 or higher machines.
The program will keep adding to the buffers in a circular fashion,
so it's the responsibility of the .DLL or .EXE to read the data
quickly enough not to miss any data.
PMIDIEventArray = ^TMIDIEventArray;
TMIDIEventArray = Array [1..1000] of TMIDIEvent
TMIDIEventArray is a circular buffer of TMIDIEvents. A TMIDIEvent
is defined as follows:
TMidiEvent = Record
Source:Word; {0 for thru; 1 for output}
Event:Longint; {MIDI Event}
End;
The source indicates whether the event was a normal output event or
a thru event.
The Event field is a long integer storing the MIDI data bytes. The
most significant byte contains the status, and the 2nd and 3rd most
significant bytes contain the data bytes, and the least significant
byte isn't used. This is the same structure that is used by
multimedia windows for MIDIOutShortMsg.
The PSysExArray is a pointer to a TSysexArray data structure as
shown below:
PSysExArray = ^TSysExArray;
TSysexArray = Array[0..64000] of Byte;
PowerTracks will fill the SysexArray field with bytes of SysexData and
then fill the TheMIDIEventArray buffer with two special $F0/$F7 events
that indicate that indicate the position of the beginning and
end of a sysex message. For example:
Source Event Interpretation
0 $903C4000 ($90 $3C $40) Note on Middle C, the source of 0 means
that MIDI thru (i.e. input) was the source of the
message.
1 $99244000 ($99 $24 $40) A Drum note was sent out the MIDI output from
PowerTracks (assuming drums are on channel 10)
(The Source=1 indicates that PTW sent the note out.)
0 $F0000000 ($F0 $00 $00) A SysEx message was received
by PTW from MIDI.
Sysex messages starts at offset $0000
0 $F7010400 ($F7 $01 $04) The SysEx message ends at offset $0104 indicating
that the message stored in the sysex is from 0 to $104,
so it is 261 bytes long.
1 $C1200000 ($C1 $20) A patch change of 33 was sent out by the program.
(assuming you consider patch numbers to begin
with 1 and end with 128)
0 $F0010500 ($F0 $01 $05) Another sysex has been stored.
0 $F7010900 ($F7 $01 $09) This one ends soon so it is only 5 bytes long.
The ProgNum parameter in the LuanchTheDialog procedure tells which
PG Music program called the .DLL. Currently only PowerTracks
interfaces with this type of DLL, but this feature could be added
to the other programs as well.
Here are the various possible values for the ProgNum parameter:
0 = Unspecified
1 = PowerTracks (the only program currently interfacing with these
.DLLs or .EXEs)
2 = Band-in-a-Box
3 = Pianist (Classical, New Orleans, or ragtime)
4 = JazzPianist
5 = Guitarist
6 = SC-PRO
A .DLL can be loaded, or an .EXE can be launched, when the user
presses the DLL button in the PowerTracks Mixer window. All DLLs
or EXEs in the same directory as PTW.EXE that begin with a dollar
sign character, e.g. $SC.DLL will appear in a dialog that lets the
user choose a .DLL or an .EXE.
Once a DLL is selected, the LaunchTheDialog Procedure will be
called by PowerTracks when the user presses the button next to the
DLL button. This button will be named 'GS' in the case of $GS.DLL.
The .DLL will remain loaded in memory until either PTW is finished
running, or the user selects a different .DLL.
(Interfacing with an .EXE involves sending the wm_MD_EXESignIn and
wm_MD_EXESignOut messages which are discussed later in this
document.)
Additional Messages: Starting with PTW 3.0b, a new set of messages
has been added to expand the capabilities of a .DLL, plus the
ability to interface with .EXEs was also added to PTW 3.0b. Since
many of these messages are appropriate for PowerTracks, only some
of them may possibly be supported by other programs.
Below are the additional messages, their numeric values will be
listed at the end of this document. Each message is listed
here by name. On the same line as the message name, we'll show
show the usage of each parameter (wParam, lParam, and result), plus
a description of the message.
MESSAGE wParam lParam Returns
wm_MD_GetVersion not used not used version
(current version is '1'. If version returned is less than 1, then
it can be assumed that these messages are not supported, and
interfacing with .EXEs isn't supported.)
wm_MD_SetTrackNumber wTrackNum not used Track Number
(This sets the track number which will be used when track-related
messages are sent such as wm_MD_InsertTrackEvent, etc. You first set
the track number, and then you can use messages to edit the
track. The wTrackNum can be a number ranging from 1 to the
highest track which is returned from the wm_MD_GetHighestTrack
message)
wm_MD_GetTrackNumber not used not used Track Number
(This returns the track number set with the wm_MD_SetTrackNumber
message)
wm_MD_GetTrackNumberOfEvents not used not used result
(This returns the number of events in a track)
wm_MD_GetHighestTrack not used not used PTW returns 48
(This returns the highest track number supported by the program.
PTW returns 48, since it has 48 tracks)
wm_MD_DeleteTrackEvent not used dwIndex result
(This deletes an event from a track. Returns 1 for success, 0
for failure)
wm_MD_UpdateScreens not used not used result
(This message updates the screens in the program. You should send
this message any time you want PTW to update its screens. For
example, if you've just did an editing routine, you should send
this message so that PTW's screens will reflect the changes you've
made.)
wm_MD_InsertTrackEvent not used PIndexedMidiData result
(This will insert an event into a track. The Lparam is a pointer
to a TIndexedMidiData structure which is as follows:
TIndexedMIDIData = Record
Index:Longint; (zero-based index of the event, 1st event has
index of zero)
MIDIData:Longint; (This is the same kind of longint used for
MIDI data as Windows 3.1 in functions
such as MIDIOutShortMsg. The least
significant byte is the status, and the
2nd and 3rd least significant bytes are
used for data bytes 1 and 2. The most
significant byte is not used. For example
a Middle C on channel 1 with a velocity of
100 ($90 $3C $64) would be $00643C90.
Keep in mind that PowerTracks stores notes as
one event with a duration rather than two separate
note on/off events)
Time:Longint; (This is a time in ticks where 0 is the song
start)
Duration:Word; (this is used for the duration if the event is
a note)
LyricText: PChar; (this is a PChar (pointer to a null terminated
string), and this field is used if the event
is a Lyric event $0000007F. Setting the
MIDI data to $0000007F tells PTW that the
event is a lyric rather than a MIDI event.
dw1:Longint; (not used)
dw2:Longint; (not used)
End;
Note: the pointer send in this message must be a valid pointer. You
can use the '@' operator in front of a TIndexedMidiData variable.
For example, if you've got a variable called MyIndexedData that is
a TIndexedMidiData, the LParam field could be Longint(@MyIndexedData).
Typecasting to a longint is necessary since the Lparam field requires
a longint.
wm_MD_ModifyTrackEvent not used PIndexedMidiData result
(this is sent to modify an event of a track. If you change the
time, the event will be moved to a different location in the
track according to the time. All fields in the PIndexedMidiData
must be set to the correct values for the event even if you're
only changing one field for the event.)
wm_MD_GetTrackEvent not used PIndexedMidiData result
(this gets an event from a track and fills the PIndexedMidiData with
the information about the event)
wm_MD_GetTrackInfo not used PTrackInfo result
(This is used to set track information such as the track name,
channel, etc. Msg.LParam is a pointer to a TTrackInfo structure
which is as follows:
TTrackInfo = Record
PlayMuteFrozenStatus:Byte; {0 = Frozen, 1 = Muted, 2 = Play)
Name:PChar; (PChar with the name of the Track. You MUST make
sure this is a valid pointer with enough space
allocated for PowerTracks to fill with a track name)
Channel:Byte; (Forced channel)
Key:ShortInt; (key transpose)
Vel:ShortInt; (forced vel +/-)
Port:Byte; (port number)
Patch:ShortInt; (prg number. -1 thru 127 -- this is always
zero-based with a value of -1 meaning no patch)
Bank:ShortInt; (bank number. -1 thru 127)
Loop:Word; (loop. 0 thru 999)
Dw1:Longint; (unused)
Dw2:Longint; (unused)
w1:Word; (unused)
i1:Integer; (unused)
End;
wm_MD_SetTrackInfo not used PTrackInfo result
(This sets the track info with the information you've placed into
a TTrackInfo structure. LParam is a Pointer to a TTrackInfo
structure. All fields must be set even if you're only changing
one field.)
wm_MD_GetSongTime not used not used Song Time in ticks
(gets current song time in ticks)
wm_MD_SetSongTime not used dwSongTime result
(sets the song time in ticks)
wm_MD_Play not used not used result
(starts playback. Returns 1 for success, 0 for failure. Failure
results if playback is already happening)
wm_MD_Stop not used not used result
(stops playback. Returns 1 for success, 0 for failure)
wm_MD_GetFromValue not used not used FromValue
(returns from value in ticks)
wm_MD_GetThruValue not used not used ThruValue
(returns thru value in ticks)
wm_MD_SetFromValue not used dwFromValue Result
(Sets from value in ticks, Returns 1 for success, 0 for failure)
wm_MD_SetThruValue not used dwThruValue Result
(Sets thru value in ticks, Returns 1 for success, 0 for failure)
wm_MD_IsTrackHighlighted wTrackNum not used Result
(Used to tell if a particular track is highlighted. This uses Wparam
for the track number)
wm_MD_GetSongPPQ not used not used SongPPQ
(Returns PPQ of the song)
wm_MD_GetNumberofMeterMapEvents not used not used dwMeterMapEvents
(Returns number of events in Meter Map)
wm_MD_GetMeterMapNumerator not used dwIndex dwNumerator
(Returns Numerator of meter map event, or zero for failure)
wm_MD_GetMeterMapDenominator not used dwIndex dwDenominator
(Returns Denominator of meter map event, or a value <= 0 indicates failure)
wm_MD_GetMeterMapTime not used dwIndex dwTime
(Returns Time in Ticks of meter map event, or -1 for failure)
wm_MD_GetMeterMapMeasure not used dwIndex dwMeasure
(Returns Measure of meter map event, or -1 for failure)
wm_MD_SetMeterMapNumerator not used dwIndex result
(Sets Numerator of Meter Map event. Returns 1 for success, 0 for failure)
wm_MD_SetMeterMapDenominator not used dwIndex result
(Sets Denominator of Meter Map event. Returns 1 for success, 0 for failure)
wm_MD_InsertMeter wMeasure dwNumeratorDenominator result
(Inserts meter map event at measure location in wMeasure (not an index).
The high word of dwNumeratorDenominator is the numerator, and the low word
is the denominator. Result is 1 for success, 0 for failure.
Duplicate entries at same measure aren't inserted by this message)
wm_MD_DeleteMeter not used dwIndex result
(This deletes meter map event at dwIndex . If only 1 meter
map event exists it won't get deleted. Returns 1 for success, 0 for failure)
wm_MD_GetTempoMapTempoValue not used dwIndex dwTempoValue
(returns Tempo value of tempo map event)
wm_MD_GetTempoMapTime not used dwIndex dwTicks
(returns time in ticks of tempo map event)
wm_MD_SetTempoMapTempoValue wTempo dwIndex Result
(returns 1 for success, 0 for failure)
wm_MD_GetNumberofTempoMapEvents not used not used dwNumberEvents
(returns number of Tempo Map events)
wm_MD_InsertTempo wTempo dwTimeInTicks Result
(returns 1 for success, 0 for failure. Will not insert multiple events
at same time location)
wm_MD_DeleteTempo not used dwIndex Result
(returns 1 for success, 0 for failure. Will not delete event if it's
the only tempo map event)
wm_MD_GetSongKeySignature not used not used dwKeySigValue
(returns value representing key signature of song ranging form -7 to 7.
The key of C = 0. Negative numbers represent flats (e.g. -1 = f,
since it has 1 flat, -7 = Cb). Numbers above zero represent sharps
(e.g. 1 = G, since the key of G has 1 sharp)
wm_MD_SaveUndoTrackData not used PChar result
(this caused PowerTracks to save the data of all the track so subsequent
editing can later be 'undone'. The PChar should be the text
that will appear in the PTW Undo menu item after the word,
'Undo'. e.g. '(Patch Strip)'. Keep it short in length. Returns 1
for success, 0 for failure)
wm_MD_Undo not used not used result
(This will restore the track data saved with wm_MD_SaveUndoTrackData, if
any data was saved. The user can also use the PTW undo so you
don't need to provide your own undo if you've send the message
to save the undo data.)
wm_MD_ExeSignIn not used PExeInfo result
(This is sent by an .EXE application to 'sign in' to
PowerTracks. This message is number wm_user_258 for the 32-bit
version of PowerTracks. Note: It used to be wm_user+240 for the 16-bit
version.
Note: Your application first has to find the main window
handle to PowerTracks, but if you're a Delphi programmer, and you
use our PGMusicLink component, this is done virtually
automatically. If you're using another language such as C++, you
could look at the source code (PGLINK.PAS) and it wouldn't be too
difficult to see how our component is able to find PTW's main window
handle, since Delphi uses the same Windows API calls that other
languages use.
An .EXE uses this message to retrieve the same
information that is retrieved when PTW calls the LaunchTheDialog
procedure in a .DLL. The PExeInfo is a pointer to a TExeInfo
structure, which is:
TEXEInfo = Record
HWindow:HWnd; (handle to main window of PowerTracks)
TheCurrentPart:Integer; (current part number. Actually channel
number of current track)
PortHandle:THandle; (handle to output port number 1 of PowerTracks)
TheMIDIInfo:PMIDIInfo; (Pointer to TMIDIINFO structure, as described
earlier in this document. This must be a
valid pointer. Make sure you don't forget
to initialize it.)
ProgNum, (ProgNum, as described earlier in this document)
Language:Byte; (don't worry about this unless you're planning to
support foreign languages. This number just
indicates what language PowerTracks is being used for
displaying text. 0 = English, 3 = Chinese, 6 = French,
7 = German, 8 = Finnish, 9 = Italian, 10=Japanese,
19=Spanish)
End;
Note: the pointer sent in this message must be a valid pointer. You
can used the '@' operator in front of a TExeInfo variable.
For example, if you've got a variable called MyExeInfo that is
a TExeInfo, the LParam field could be Longint(@MyExeInfo).
Typecasting to a longint is necessary since the Lparam field requires
a longint.
If the Sign In is successful, this message will return 1. If
another .EXE is already signed in, or a .DLL is active it will
return 0.
Your .EXE should be named beginning with the '$' character, e.g.
'$MYEXE.EXE', so that it can be launched from within PTW.
wm_MD_ExeSignOut not used not used result
(this causes the currently signed in .EXE to be signed out of PowerTracks.
Returns 1 for success, 0 for failure. Do not send this message
unless the program is currently successfully signed into PTW.)
wm_MD_SaveFile not used PCharName result
(This will cause PTW to save the current song to the file named
in PCharName. PTW's file name will then be set to that name.
PCharName must be a valid PChar)
wm_MD_LoadFile not used PCharName result
(This will cause PTW to load the file named in PCharName.
PCharName must be a valid PChar)
wm_MD_GetCurrentFileName not used PCharName result
(Returns PTW's current file name by filling PCharName. PCharName
must be a valid PChar with at least 80 characters allocated to it)
wm_MD_GetCurrentTrack not used not used dwTrackNumber
(Returns number of the currently selected track in the Tracks
Window)
wm_MD_IsPlayBackHappening not used not used result
(returns 1 if playback is happening, or 0 if playback isn't
happening)
wm_MD_GetOutputPortHandle wPortNum not used dwPortHandle
(This can be used to obtain the output port handle of ports 1
through 16 in PowerTracks. We added this because only the handle
to port 1 is obtained during initialization. wPortNum can be
a number from 1 through 16. If you attempt to retrieve the
handle of a port that is greater than the max available, but within
the 1- 16 range, then the handle returned will be the handle to the
highest available port. For example, if only one output port is
available, a wPortNum value of 2 will give you the handle to Port 1.
You can use the wm_MD_GetNumberOfOutputPorts to return the number
of currently available output ports in PTW.)
wm_MD_GetNumberOfOutputPorts not used not used dwNumberOfPorts
(this returns the number of currently available output ports in
PTW, or 0 if no ports are available)
wm_MD_IsPowerTracks not used not used not used
(This returns 259. The PG Music Link component will send this
message to a window to determine if PowerTracks instead of
another application such as the PowerTracks .HLP file.
If 259 is returned in Msg.Result, then the window is assumed to
be the main window of PowerTracks. If 259 isn't returned then
the window is assumed to be another program such as the .HLP
file.)
wm _MD_SendShortMsg wPortNum LDataArray
(This will will let you send MIDI data via PowerTracks in the form
of a short MIDI output message. WParam should be set to a port
number (1 to 16) and LParam should be a LongInteger which contains
the MIDI data in the same 4-byte format as required by MidiOutShortMsg.
The reason this message is implemented is because WindowsXP won't
let an .EXE MIDI plugin directly send a MIDI output message using
the porthandles that were opened in PowerTracks. In other words XP
doesn't let apps share the same port handle, so we created this
message that lets you send a MIDI message by routing it through
PowerTracks.)
DIFFERENCES BETWEEN INTERFACING .EXES AND .DLLS TO POWERTRACKS
Starting with PTW 3.0b, .EXEs can now be interfaced to PowerTracks.
EXEs are stand-alone applications as opposed to DLLs which are
libraries that are loaded by EXE applications.
Advantages of using .DLLs as opposed to EXEs:
1) A .DLL can have a dialog that will behave as if it were built-in
to PTW. This true if you create a .DLL that has a modal dialog
(one that doesn't let you switch to another window in the program
unless you hit OK) An example of this is our $GS.DLL. When the GS
dialog pops up, you can't switch to another window in PowerTracks,
so it won't get obscured.
NOTE: On the other hand, you may want to allow the user to be able
to switch back and forth between the window of your program so this
is only really an advantage if you want a modal dialog.
2) DLLs remain in memory until unloaded by PowerTracks so you can
create an editing dialog, such as the $GS.DLL, that stores the
current settings in memory after the dialog has been closed during
the current session and will re-display them the next time the
dialog is popped-up during the current PTW session.
3) You can have a high resolution multimedia timer interrupt in a
.DLL. You could have an .EXE that makes use of an MM timer
interrupt but the .EXE itself would then have use a .DLL for all
the MM timer interrupt callback routines. (You can, of course,
have ordinary (non-multimedia) low resolution windows timer
routines in an .EXE.)
4) You can call MidiOutShortMsg and MidiOutLongMsg directly with
the same port handles that are used by PowerTracks. (Note: We
created a WM_MD_SendShortMsg that can be used to send a short
message via PTW. THis works for both DLLs and EXEs)
Advantages to using an .EXE as opposed to a .DLL:
1) An .EXE is easier to debug than a .DLL. In fact, Delphi itself
can't debug a .DLL. You would have to purchase the latest version
of Turbo Debugger for Windows. On the other hand, you could first
make your program an .EXE, and then, when you've got it debugged,
you could make it into a .DLL, assuming it doesn't use any
multimedia timer (MMSYSTEM) routines.
2) An .EXE could be written in such a way that, instead of being
launched by PTW, it could be run by itself, and will find PTW (or
launch PTW if necessary). While this launching feature is a nice
feature, it is more important that an .EXE be written so that it
can be launched by Powertracks rather than the other way around.
3) The PGMusicLink Component. Our demo .EXE program, EXEDEMO.DPR,
is a Delphi Project that contains a component called PGMusicLink,
and is contained in PGLINK.PAS. The component makes it very easy
for an .EXE to link to PowerTracks. You can use it for your .EXE
applications. You don't have to use it, but, if you're using
Delphi, then using this component makes creating your application
easier. Keep in mind that even if you've launched an .EXE from
within PowerTracks the .EXE still has to locate PTW.EXE's main
window handle and the PGMusicLink component takes care of this for
you.
USING THE PGMUSICLINK COMPONENT:
The following will explain how you can use the PGMusicLink
component in your applications. We've included a demo .EXE program
written in Delphi, called EXEDEMO.DPR. All the source code is
included, so you can study it in addition to this documentation.
To use the component, you first load it into the Delphi component
library using the Options | Install Components command. This will
bring up a dialog that will let you add PGLINK.PAS to the component
library. After you've installed the component, Delphi will
recompile the component library, and then it will appear in the
component palette in the 'Samples' page. You can then click on the
component and drag it to the main form of the application.
Your application can launch PTW simply by referencing the
component's MainWinHandle property. The component takes care of
issues such as finding PTW if it's already running, launching it if
necessary, and prompting the user for the path name if necessary.
If this property is equal to zero, then that means the component
could not link to PTW. The component issues error messages to the
user and gives the user a chance to correct errors such as an
incorrect path name. Since the component does all this work, if it
should turn out that this property is equal to zero (e.g. if your
window's PGMusicLink component is called PGMusicLink1, and
PGMusicLink.MainWinHandle = 0) your application can assume the
component couldn't link and the user has already been informed of
this, so your program could simply issue one final message such as
'Could Not Link To PowerTracks, quitting...' and then simply stop
executing as our EXEDEMO.DPR application does.
You can give the user a chance to link to a different program after
initialization. For example, if we eventually add linking support
to other programs such as Band-in-a-Box, then having a 'Choose
.EXE' button on your main window could let the .EXE be used
with other programs. There is a component method called
PromptUserForExeName which brings up a dialog prompting the user to
choose a different .EXE to link to, and returns true if the user
selected a different .EXE name. If the user has chosen a different
.EXE, then the component signs out of the currently linked .EXE.
Your application then just has to reference the MainWinHandle
property again to obtain the handle to the new .EXE, and if the
handle is equal to 0 then that means linking to the different .EXE
failed (and the component has already issues error message and
given the user a chance to enter a different path name, etc).
If the user is ever prompted for a different .EXE name and presses
OK, the path of that .EXE will be stored in a file called
PGLINK.INI which resides in the directory of your application.
This file will be read by the component the next time your
application is run.
If we add linking support to other programs besides PTW, and your
application were meant for use with another program, such as BBW, you
can change the default name of the .EXE that the component links to
by editing the ExeName property at design time. By default, the
.EXE name is set to 'PTW.EXE'. You could set it to, say, 'BBW.EXE'
if we added linking support to BBW and your .EXE were designed to
link to BBW rather than PowerTracks.
In summary, the PGMusicLink component has two properties and one
method function that you need to be aware of:
1) The MainWinHandle property which, when referenced by your
application (e.g TheHandle := PGMusicLink1.MainWinHandle) will
either obtain the handle to PTW or will return 0 if the component
couldn't link.
2) The ExeName property, which can be changed at design time.
3) The PromptUserForExeName Function that you can use to give the
user a chance to link to a different .EXE after initial linking was
successful.
Here's a list of all the messages with their numeric values:
Const wm_MD_BufferNotNeeded = wm_User + 33;
Const wm_MD_GetVersion = wm_User + 200;
Const wm_MD_SetTrackNumber = wm_User + 201;
Const wm_MD_GetTrackNumber = wm_User + 202;
Const wm_MD_GetTrackNumberOfEvents = wm_User + 203;
Const wm_MD_GetHighestTrack = wm_User + 204;
Const wm_MD_DeleteTrackEvent = wm_User + 205;
Const wm_MD_UpdateScreens = wm_User + 206;
Const wm_MD_InsertTrackEvent = wm_User + 207;
Const wm_MD_ModifyTrackEvent = wm_User + 208;
Const wm_MD_GetTrackEvent = wm_User + 209;
Const wm_MD_GetTrackInfo = wm_User + 210;
Const wm_MD_SetTrackInfo = wm_User + 211;
Const wm_MD_GetSongTime = wm_User + 212;
Const wm_MD_SetSongTime = wm_User + 213;
Const wm_MD_Play = wm_User + 214;
Const wm_MD_Stop = wm_User + 215;
Const wm_MD_GetFromValue = wm_User + 216;
Const wm_MD_GetThruValue = wm_User + 217;
Const wm_MD_SetFromValue = wm_User + 218;
Const wm_MD_SetThruValue = wm_User + 219;
Const wm_MD_IsTrackHighlighted = wm_User + 220;
Const wm_MD_GetSongPPQ = wm_User + 221;
Const wm_MD_GetNumberofMeterMapEvents = wm_User + 222;
Const wm_MD_GetMeterMapNumerator = wm_User + 223;
Const wm_MD_GetMeterMapDenominator = wm_User + 224;
Const wm_MD_GetMeterMapTime = wm_User + 225;
Const wm_MD_GetMeterMapMeasure = wm_User + 226;
Const wm_MD_SetMeterMapNumerator = wm_User + 227;
Const wm_MD_SetMeterMapDenominator = wm_User + 228;
Const wm_MD_InsertMeter = wm_User + 229;
Const wm_MD_DeleteMeter = wm_User + 230;
Const wm_MD_GetTempoMapTempoValue = wm_User + 231;
Const wm_MD_GetTempoMapTime = wm_User + 232;
Const wm_MD_SetTempoMapTempoValue = wm_User + 233;
Const wm_MD_GetNumberofTempoMapEvents = wm_User + 234;
Const wm_MD_InsertTempo = wm_User + 235;
Const wm_MD_DeleteTempo = wm_User + 236;
Const wm_MD_GetSongKeySignature = wm_User + 237;
Const wm_MD_SaveUndoTrackData = wm_User + 238;
Const wm_MD_Undo = wm_User + 239;
Const wm_MD_ExeSignIn = wm_User + 258;
Const wm_MD_ExeSignOut = wm_User + 241;
Const wm_MD_SaveFile = wm_User + 242;
Const wm_MD_LoadFile = wm_User + 243;
Const wm_MD_GetCurrentFileName = wm_User + 244;
Const wm_MD_GetCurrentTrack = wm_User + 245;
Const wm_MD_IsPlayBackHappening = wm_User + 246;
Const wm_MD_GetOutputPortHandle = wm_User + 247;
Const wm_MD_GetNumberOfOutputPorts = wm_User + 248;
Const wm_MD_ExeSignIn = wm_User + 258;
Const wm_MD_IsPowerTracks = wm_user + 259;
Const wm_MD_SendShortMsg = wm_user + 260
----------------------End of Document - PTWDLL.TXT--------------